import type { Logger } from 'winston'
import { format } from 'winston'

export class LoggerWrapper {
  static createFormatPrintf() {
    return format.printf((info) => {
      const { level, message, timestamp, meta } = info

      let text = ''
      let metaWrap = false

      if (timestamp) {
        text += timestamp + ' '
      }

      text += `${level.padStart(5, ' ')}: ${message}`

      if (info instanceof Error && info.stack) {
        text += `\n${info.stack}`
        metaWrap = true
      }

      if (meta && meta.length > 0) {
        text += (metaWrap ? '\n' : ' ') + JSON.stringify(meta)
      }

      return text
    })
  }

  readonly logger: Logger

  constructor(logger: Logger) {
    this.logger = logger
  }

  log(level: LogLevel, message: Message, ...meta: any[]) {
    if (this.logger.destroyed) {
      // TODO 日志记录器销毁可能还在记录日志，这里需要处理
      // console.error(level, message, meta)
      return
    }
    if (typeof message === 'string') {
      this.logger.log(level, message, { meta })
    } else if (message instanceof Error) {
      // @ts-ignore
      message.meta = meta
      this.logger.log(level, message)
    } else {
      this.logger.log(level, String(message), { meta })
    }
  }

  error(message: Message, ...meta: any[]) {
    return this.log('error', message, ...meta)
  }

  warn(message: Message, ...meta: any[]) {
    return this.log('warn', message, ...meta)
  }

  info(message: Message, ...meta: any[]) {
    return this.log('info', message, ...meta)
  }

  http(message: Message, ...meta: any[]) {
    return this.log('http', message, ...meta)
  }

  verbose(message: Message, ...meta: any[]) {
    return this.log('verbose', message, ...meta)
  }

  debug(message: Message, ...meta: any[]) {
    return this.log('debug', message, ...meta)
  }

  silly(message: Message, ...meta: any[]) {
    return this.log('silly', message, ...meta)
  }
}

export type LogLevel = 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly'

export type Message = any
